package com.um.jdy.app.user.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.um.jdy.app.user.entity.dto.MonthCardBuyParam;
import com.um.jdy.app.user.entity.dto.MonthCardUpgradeParam;
import com.um.jdy.app.user.entity.vo.UpgradeCardPackageVO;
import com.um.jdy.app.user.entity.vo.UpgradePackageVO;
import com.um.jdy.baofu.api.BaofuPayService;
import com.um.jdy.common.charge.entity.po.Order;
import com.um.jdy.common.charge.enums.OrderEnum;
import com.um.jdy.common.commons.manager.WxManager;
import com.um.jdy.common.commons.service.CommissionService;
import com.um.jdy.common.finance.entity.po.PlatformBill;
import com.um.jdy.common.finance.entity.po.UserBill;
import com.um.jdy.common.finance.enums.FinancialEnum;
import com.um.jdy.common.finance.service.PlatformBillService;
import com.um.jdy.common.finance.service.UserBillService;
import com.um.jdy.common.member.entity.po.MemberUser;
import com.um.jdy.common.member.enums.PayEnum;
import com.um.jdy.common.member.service.MemberUserService;
import com.um.jdy.common.month.code.MonthCode;
import com.um.jdy.common.month.entity.po.CardOrder;
import com.um.jdy.common.month.entity.po.CardPackage;
import com.um.jdy.common.month.entity.po.CardUser;
import com.um.jdy.common.month.entity.vo.CardPackageVO;
import com.um.jdy.common.month.service.CardOrderService;
import com.um.jdy.common.month.service.CardPackageService;
import com.um.jdy.common.month.service.CardUserService;
import com.um.jdy.common.platform.entity.po.App;
import com.um.jdy.common.platform.service.AppService;
import com.um.springboot.starter.exception.ServiceException;
import com.um.springboot.starter.orm.entity.Response;
import com.um.springboot.starter.properties.HshProperties;
import com.um.springboot.starter.utils.OrderUtil;
import com.um.springboot.starter.utils.PayUtil;
import com.um.springboot.starter.utils.StringUtil;
import com.um.springboot.starter.utils.UMBeanUtils;
import com.um.weixin.pay.service.WxBasePayService;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.*;

/**
 * @Title
 * @Description
 * @Author renjunwei
 * @Date 2023/5/22 10:37
 */
@Slf4j
@Service
public class MonthCardManager {

    @Autowired
    CardPackageService cardPackageService;

    @Autowired
    MemberUserService memberUserService;

    @Autowired
    CardOrderService cardOrderService;

    @Autowired
    CardUserService cardUserService;

    @Autowired
    HshProperties hshProperties;

    @Autowired
    TaskScheduler taskScheduler;

    @Autowired
    WxManager wxManager;

    @Autowired
    WxBasePayService wxPayService;

    @Autowired
    UserBillService userBillService;

    @Autowired
    PlatformBillService platformBillService;

    @Autowired
    CommissionService commissionService;

    @Autowired
    BaofuPayService baofuPayService;

    @Autowired
    AppService appService;


    /**
     * 查询网点月卡套餐列表
     * @param station_id
     * @return
     */
    public List<CardPackageVO> getPackageList(String station_id) {
        List<CardPackage> list = cardPackageService.getList(new String[]{"device_station_id"},new Object[]{station_id},
                new String[]{"max_power"},new String[]{"asc"});
        return UMBeanUtils.copyBeanList(list,CardPackageVO.class);
    }

    /**
     * 月卡套餐购买
     * @param param
     * @return
     */
    public Map packageBuy(MonthCardBuyParam param){
        //查询套餐
        CardPackage cardPackage = cardPackageService.getEntity(param.getMonthCardPackageId());
        if (cardPackage == null)
            throw new ServiceException(MonthCode.NoPackage);

        int payAmount = cardPackage.getPrice();

        CardOrder order = new CardOrder();
        order.setOrderNo(OrderUtil.getOrderNo());
        order.setOutTradeNo(OrderUtil.getWxOrderNo());
        order.setMemberUserId(memberUserService.get().getMemberUserId());
        order.setDeviceStationId(cardPackage.getDeviceStationId());
        order.setMaxPower(cardPackage.getMaxPower());
        order.setCreateTime(new Date());
        order.setPackageAmount(payAmount);
        order.setPayAmount(payAmount);
        order.setPayWay(param.getPayWay().name());
        order.setPayStatus(PayEnum.Status.UnPayed.name());
        order.setStartDate(new Date());
        order.setEndDate(DateUtil.offsetMonth(new Date(),1));
        order.setMonthCardPackageId(param.getMonthCardPackageId());
        log.info("=====购买月卡套餐outTradeNo：" + order.getOutTradeNo());
        cardOrderService.save(order);

        MemberUser user = memberUserService.get();
        if (PayEnum.PayWay.Wxpay == param.getPayWay()) { //微信支付
            //预下单，生成支付参数
            String openId = user.getMiniOpenId();
            /** todo 修改成宝付支付
            String notifyUrl = StrUtil.builder(hshProperties.getConfig().getDomain(),
                    "/api/v1/user/month_card/wxpay/notify/", user.getComId()).toString();

            WxPayUnifiedOrderV3Result.JsapiResult jsapiResult = null;
            try {
                wxManager.getPayService(user.getComId());
                jsapiResult = wxPayService.createOrderByJsapi(order.getOutTradeNo(), openId,
                        PayUtil.toTotalFee(payAmount), PayEnum.Title.MonthCard.getValue(), notifyUrl, false);
            } catch (WxPayException e) {
                throw new RuntimeException(e);
            }

            Map<String, Object> returnData = BeanUtil.beanToMap(jsapiResult, true, true);
            returnData.put("monthcard_order_id", order.getMonthCardOrderId());
            returnData.put("order_no", order.getOrderNo());
            */
            String type ="monthCard";
            App app = appService.getEntity("com_id", cardPackage.getComId());
            Map<String, Object> returnData = baofuPayService.createOrderByJsapi(order.getOutTradeNo(),PayUtil.toTotalFee(payAmount),PayEnum.Title.MonthCard.getValue(),openId,app.getMiniAppId(),app.getWxMchId(),type,user.getComId());
            //Map<String, Object> returnData = null;
            returnData.put("monthcard_order_id", order.getMonthCardOrderId());
            returnData.put("order_no", order.getOrderNo());
            return returnData;
        } else {
//            String notifyUrl = StrUtil.builder(hshProperties.getConfig().getDomain(), "/api/v1/notify/month_card_buy/notify").toString();
//            //微信支付
//            String openId = StringUtil.getTrim(user.get("mini_open_id"));
//            Map prepay = PayAPI.prepay(openId, outTradeNo, payUtil.toTotalFee(payAmount), request.getLocalAddr(), notifyUrl, PayEnum.Title.MONTH_CARD.getValue());
//            return com.hsh.hshweixin.utils.PayUtil.toPayData(prepay);
        }

        return new Hashtable();
    }


    /**
     * 查询升级月卡套餐列表
     * @param package_id
     * @return
     */
    public UpgradePackageVO getUpgradePackageList(String package_id) {

        UpgradePackageVO upgradePackageVO = new UpgradePackageVO();
        List<UpgradeCardPackageVO> returnList = new ArrayList<>();

        CardPackage cardPackage = cardPackageService.getEntity(package_id);
        if(cardPackage == null) {
            return upgradePackageVO;
        }

        List<CardPackage> list = cardPackageService.getList(new String[]{"device_station_id"},new Object[]{cardPackage.getDeviceStationId()},
                new String[]{"max_power"},new String[]{"asc"});

        for(CardPackage item : list){
            if(item.getMaxPower() > cardPackage.getMaxPower()){
                returnList.add(UMBeanUtils.copyBean(item,UpgradeCardPackageVO.class));
            }
        }

        CardOrder cardOrder = cardOrderService.getEntity(new String[]{"month_card_package_id","member_user_id","pay_status"},
                new Object[]{package_id,memberUserService.get().getMemberUserId(),PayEnum.Status.Payed.name()});

        for(UpgradeCardPackageVO item : returnList){
            CardUser cardUser = cardUserService.getEntityBySqlName("get_user_station_month_card",cardOrder.getComId(),cardOrder.getMemberUserId(),cardOrder.getDeviceStationId());
            //计算月卡开始时间和结束时间的总天数
            long totalDays = DateUtil.between(cardUser.getStartDate(), cardUser.getEndDate(), DateUnit.DAY);
            //计算月卡剩余天数
            long remainDays = DateUtil.between(DateUtil.parseDate(DateUtil.format(new Date(),"yyyy-MM-dd")), cardUser.getEndDate(), DateUnit.DAY);
            //支付差价:1、计算出每天需要补的差价 2、每天的差价再乘以天数
            int price = (int)Math.round(NumberUtil.mul(NumberUtil.div(item.getPrice() - cardPackage.getPrice(), totalDays), remainDays));
            item.setPriceDifference(price);
        }
        upgradePackageVO.setCurrent(UMBeanUtils.copyBean(cardPackage,CardPackageVO.class));
        upgradePackageVO.setUpgrades(returnList);

        return upgradePackageVO;
    }

    /**
     * 升级月卡套餐
     * @param param
     * @return
     */
    public Map packageUpgrade(MonthCardUpgradeParam param){
        //查询套餐
        CardPackage cardPackage = cardPackageService.getEntity(param.getUpgradePackageId());
        if (cardPackage == null)
            throw new ServiceException(MonthCode.NoPackage);

        List<CardOrder> cardOrders = cardOrderService.getList(new String[]{"member_user_id","device_station_id","pay_status"},
                new Object[]{memberUserService.get().getMemberUserId(),cardPackage.getDeviceStationId(),PayEnum.Status.Payed.name()},
                new String[]{"create_time"},new String[]{"desc"});

        CardOrder cardOrder = null;
        for(CardOrder item : cardOrders){
            if(!StringUtil.equals(item.getReturnStatus(), OrderEnum.ReturnStatus.Success.name())){
                cardOrder = item;
                break;
            }
        }

        int payAmount = 0;
        if(cardOrder == null){//没有旧订单，按原价购买
            payAmount = cardPackage.getPrice();
        }else{
            CardUser cardUser = cardUserService.getEntityBySqlName("get_user_station_month_card",cardOrder.getComId(),cardOrder.getMemberUserId(),cardOrder.getDeviceStationId());
            //计算月卡开始时间和结束时间的总天数
            long totalDays = DateUtil.between(cardUser.getStartDate(), cardUser.getEndDate(), DateUnit.DAY);
            //计算月卡剩余天数
            long remainDays = DateUtil.between(DateUtil.parseDate(DateUtil.format(new Date(),"yyyy-MM-dd")), cardUser.getEndDate(), DateUnit.DAY);
            //支付差价:1、计算出每天需要补的差价 2、每天的差价再乘以天数
            payAmount = (int)Math.round(NumberUtil.mul(NumberUtil.div(cardPackage.getPrice() - cardOrder.getPackageAmount(), totalDays), remainDays));

        }



        CardOrder order = new CardOrder();
        order.setOrderNo(OrderUtil.getOrderNo());
        order.setOutTradeNo(OrderUtil.getWxOrderNo());
        order.setMemberUserId(memberUserService.get().getMemberUserId());
        order.setDeviceStationId(cardPackage.getDeviceStationId());
        order.setMaxPower(cardPackage.getMaxPower());
        order.setCreateTime(new Date());
        order.setPackageAmount(cardPackage.getPrice());
        order.setPayAmount(payAmount);
        order.setPayWay(param.getPayWay().name());
        order.setPayStatus(PayEnum.Status.UnPayed.name());
        order.setStartDate(new Date());
        order.setEndDate(DateUtil.offsetMonth(new Date(),1));
        order.setMonthCardPackageId(param.getUpgradePackageId());
        order.setLastOrderId(cardOrder != null ? cardOrder.getMonthCardOrderId() : null);
        order.setRemark(String.format("套餐升级，原订单号:%s",(cardOrder != null ? cardOrder.getOrderNo() : "无")));
        cardOrderService.save(order);

        MemberUser user = memberUserService.get();
        if (PayEnum.PayWay.Wxpay == param.getPayWay()) { //微信支付
            //预下单，生成支付参数
            String openId = user.getMiniOpenId();
            String notifyUrl = StrUtil.builder(hshProperties.getConfig().getDomain(),
                    "/api/v1/user/month_card/wxpay/notify/", user.getComId()).toString();
            //log.info("月卡回调url:{}",notifyUrl);
            /**todo 修改成宝付支付
            WxPayUnifiedOrderV3Result.JsapiResult jsapiResult = null;
            try {
                wxManager.getPayService(user.getComId());
                jsapiResult = wxPayService.createOrderByJsapi(order.getOutTradeNo(), openId,
                        PayUtil.toTotalFee(payAmount), PayEnum.Title.MonthCard.getValue(), notifyUrl, false);
            } catch (WxPayException e) {
                throw new RuntimeException(e);
            }


            Map<String, Object> returnData = BeanUtil.beanToMap(jsapiResult, true, true);
            returnData.put("monthcard_order_id", order.getMonthCardOrderId());
            returnData.put("order_no", order.getOrderNo());
            */
            String type ="monthCard";
            App app = appService.getEntity("com_id", user.getComId());
            Map<String, Object> returnData = baofuPayService.createOrderByJsapi(order.getOutTradeNo(),PayUtil.toTotalFee(payAmount),PayEnum.Title.MonthCard.getValue(),openId,app.getMiniAppId(),app.getWxMchId(),type,user.getComId());
            //Map<String, Object> returnData = null;
            returnData.put("monthcard_order_id", order.getMonthCardOrderId());
            returnData.put("order_no", order.getOrderNo());
            return returnData;
        } else {
//            String notifyUrl = StrUtil.builder(hshProperties.getConfig().getDomain(), "/api/v1/notify/month_card_buy/notify").toString();
//            //微信支付
//            String openId = StringUtil.getTrim(user.get("mini_open_id"));
//            Map prepay = PayAPI.prepay(openId, outTradeNo, payUtil.toTotalFee(payAmount), request.getLocalAddr(), notifyUrl, PayEnum.Title.MONTH_CARD.getValue());
//            return com.hsh.hshweixin.utils.PayUtil.toPayData(prepay);
        }

        return new Hashtable();
    }



    /**
     * 微信支付回调
     *
     * @param request
     */
    public void wxPayNotify(HttpServletRequest request, String comId) {
        log.error("月卡支付回调：{}",comId);
        WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = null;
        try {
            wxManager.getPayService(comId);
            wxPayOrderNotifyV3Result = wxPayService.parseOrderNotify(request);
            log.error("月卡支付回调：{},{}",wxPayOrderNotifyV3Result.getResult().getOutTradeNo(),wxPayOrderNotifyV3Result.getResult().getSuccessTime());
        } catch (WxPayException e) {
            log.error("解析微信支付通知失败", e);
        }

        monthCardBuyNotify(wxPayOrderNotifyV3Result.getResult().getOutTradeNo(),
                DateUtil.parse(wxPayOrderNotifyV3Result.getResult().getSuccessTime()));

    }

    /**
     * 月卡支付回调
     *
     * @param outTradeNo
     * @param payTime
     */
    @Transactional
    public void monthCardBuyNotify(String outTradeNo, Date payTime) {
        CardOrder cardOrder = cardOrderService.getRow("out_trade_no", outTradeNo);
        if (null == cardOrder) {
            log.error("微信月卡订单" + outTradeNo + "不存在！");
            return;
        }

        if(cardOrder.getPayStatus().equals(PayEnum.Status.Payed.name())) {
            log.error("微信月卡订单" + outTradeNo + "已支付！");
        }



        CardUser cardUser = cardUserService.getRow(new String[]{"com_id","member_user_id","device_station_id"},
                new Object[]{cardOrder.getComId(),cardOrder.getMemberUserId(),cardOrder.getDeviceStationId()});
        if(cardUser == null)
            cardUser = new CardUser();

        cardUser.setComId(cardOrder.getComId());
        cardUser.setMonthCardPackageId(cardOrder.getMonthCardPackageId());
        cardUser.setMemberUserId(cardOrder.getMemberUserId());
        cardUser.setDeviceStationId(cardOrder.getDeviceStationId());
        cardUser.setMaxPower(cardOrder.getMaxPower());
        cardUser.setStartDate(cardOrder.getStartDate());
        cardUser.setEndDate(cardOrder.getEndDate());
        cardUserService.saveRow(cardUser);

        //记录账户流水，金额为支付金额
        //充值余额
        UserBill userBill = new UserBill();
        userBill.setComId(cardOrder.getComId());
        userBill.setMemberUserId(cardOrder.getMemberUserId());
        userBill.setNo(OrderUtil.getOrderNo());
        userBill.setOutTradeNo(cardOrder.getOutTradeNo());
        userBill.setOrderNo(cardOrder.getOrderNo());
        userBill.setAmount(cardOrder.getPayAmount());
        userBill.setType(FinancialEnum.IncomeOrExpend.Expend.name());
        userBill.setEvent(FinancialEnum.UserBillEvent.MonthCard.name());
        userBill.setStatus(FinancialEnum.BillStatus.Effective.name());
        userBill.setCreateTime(DateUtil.date());
        userBillService.saveRow(userBill);

        //插入平台收支流水：套餐充值
        PlatformBill platformBill = new PlatformBill();
        platformBill.setComId(cardOrder.getComId());
        platformBill.setNo(OrderUtil.getOrderNo());
        platformBill.setOutTradeNo(cardOrder.getOutTradeNo());
        platformBill.setOrderNo(cardOrder.getOrderNo());
        platformBill.setAmount(cardOrder.getPayAmount());
        platformBill.setType(FinancialEnum.IncomeOrExpend.Income.name());
        platformBill.setEvent(FinancialEnum.PlatformBillEvent.MonthCard.name());
        platformBill.setStatus(FinancialEnum.BillStatus.Effective.name());
        platformBill.setCreateTime(DateUtil.date());
        platformBillService.saveRow(platformBill);

        //月卡分佣
        int profit = commissionService.calcMonthCardCommission(cardOrder.getMonthCardOrderId(),cardOrder.getDeviceStationId(),cardOrder.getCreateTime(),
                cardOrder.getOrderNo(),cardOrder.getOutTradeNo(),cardOrder.getPayAmount());

        cardOrder.setPayStatus(PayEnum.Status.Payed.name());
        cardOrder.setPayTime(payTime);
        cardOrder.setProfit(profit);
        cardOrderService.saveRow(cardOrder);

    }

    /**
     * 宝付微信支付回调
     *
     *
     */
    public void BaofuWxPayNotify(String outTradeNo,String successTime, String comId) {
        log.error("宝付月卡回调：{}",comId);
//        WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = null;
//        try {
//            wxManager.getPayService(comId);
//            wxPayOrderNotifyV3Result = wxPayService.parseOrderNotify(request);
//            log.error("月卡支付回调：{},{}",wxPayOrderNotifyV3Result.getResult().getOutTradeNo(),wxPayOrderNotifyV3Result.getResult().getSuccessTime());
//        } catch (WxPayException e) {
//            log.error("解析微信支付通知失败", e);
//        }

        monthCardBuyNotify(outTradeNo, DateUtil.parse(successTime));

    }

//    public static void main(String[] args) {
//        System.out.println(DateUtil.between(DateUtil.parseDate("2024-09-03"), DateUtil.parseDate("2024-10-03"), DateUnit.DAY));
//    }

}
